const puppeteer = require("puppeteer");

const sleep = (numberMillis) => new Promise((resolve) => {   // 设定异步睡眠时间
    setTimeout(resolve, numberMillis);
})

const randomNum = (min, max) => {                           // 指定范围内随机整数
    
    var random = Math.floor(Math.random() * (max - min + 1) + min)
    return random
}

async function createBrowser() {                            // 创建一个Browser对象
    console.log(puppeteer.executablePath());
    return await puppeteer.launch({
        headless: false,
        ignoreHTTPSErrors: true,
        dumpio: true,
        args: [
            "--no-sandbox",
            "--disable-setuid-sandbox",
        ], 
        timeout: 30000,
        executablePath: puppeteer.executablePath().replace("app.asar", "app.asar.unpacked")
    })
}

async function preparePageForTests(page) {                  // 修改JS参数
    // Pass the User-Agent Test.
    const userAgent = useragents[parseInt(Math.random() * useragents.length)]
    await page.setUserAgent(userAgent);
    await page.setViewport({ width: 980, height: 703 })

    // Pass the Webdriver Test.
    await page.evaluate(() => {
      Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined,
      });
    });
    await sleep(800);

    // Pass the Chrome Test.
    await page.evaluate(() => {
      // We can mock this in as much depth as we need for the test.
      window.navigator.chrome = {
        runtime: {},
        app: {},
        // etc.
      };
    });
    await sleep(800);
  
    // Pass the Permissions Test.
    await page.evaluate(() => {
      const originalQuery = window.navigator.permissions.query;
      return window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
          Promise.resolve({ state: Notification.permission }) :
          originalQuery(parameters)
      );
    });
    await sleep(800);
  
    // Pass the Plugins Length Test.
    await page.evaluate(() => {
      // Overwrite the `plugins` property to use a custom getter.
      Object.defineProperty(navigator, 'plugins', {
        get: () => [1, 2, 3],
      });
    });
    await sleep(800);
  
    // Pass the Languages Test.
    await page.evaluate(() => {
      // Overwrite the `plugins` property to use a custom getter.
      Object.defineProperty(navigator, 'languages', {
        get: () => ["zh-CN", "zh"],
      });
    });

    return;
}

async function preparePageForModify(page) {                 // 修改JS参数
    let count = 0;
    while (count <= 3) {
        await preparePageForTests(page);

        if (window.navigator.webdriver == true) {
            count++;
            sleep(1000);
        } else {
            break;
        }
    }
    console.log("当前的js参数：" + window.navigator.webdriver);
    return;
}


async function dragSlider2Verify(page) {                    // 拖动滑块验证
    let error = "";

    await page.$(".nc-lang-cnt");
    const initText = await page.$eval(".nc-lang-cnt", el => el.textContent);
    console.log("*** 滑块初始文本 ***", initText);
    if (initText.search("网络不给力") != -1) {
        try{                // Refresh the page.
            const refreshBtn = await page.$x("//*[@id='dom_id']/div/span[@class='nc-lang-cnt']/a[1]")
            await refreshBtn[0].click();
            await sleep(randomNum(1, 3) * 1000);
        } catch(err) {
            console.log("*** refresh error ****", err);
        }
    }

    await page.waitFor("#nc_1_n1z");                        // 等待滑块元素加完成
    const slider = await page.$("#nc_1_n1z");
    const size = await slider.boundingBox();

    await dragActions(page, size);                          // 模拟人为拖动

    // 校验结果
    await page.$(".nc-lang-cnt");
    const sliderAgain = await page.$eval(".nc-lang-cnt", el => el.textContent);
    console.log("*** 滑块验证结果 ***", sliderAgain);
    if (sliderAgain != "验证通过") {
        if (sliderAgain === "哎呀，出错了，点击刷新再来一次") {
            console.log("环境被检测到，未能正常绕过JS检测...");
            error = "401";      // 环境被检测
        }
        else if(sliderAgain === "加载中") {
            console.log("*******执行加载中");
            while (void 0 != 1) {
                const loadText = await page.$eval(".nc-lang-cnt", el => el.textContent)
                if (loadText != "加载中") {
                    console.log(loadText);
                    if (loadText === "哎呀，出错了，点击刷新再来一次") {
                        error = "401";
                        break
                    }
                    else if(loadText === "验证通过") {
                        error = "";
                        break
                    }
                    else if (loadText === "请按住滑块，拖动到最右边") {
                        await dragActions(page, size);                          // 模拟人为拖动
                    }
                    else{
                        error = "400";
                        break;
                    }
                    
                }
                await sleep(randomNum(1, 3) * 1000);
            }
        }
        else if(sliderAgain.search("网络不给力") != -1) {
            console.log("*******网络不给力");
            error = "400";
        }
        else {
            console.log("验证不通过，错误信息：", sliderAgain);
            error = "400";
        }
        
    }
    return error;
}

async function dragActions(page, size) {                    // 模拟拖动
    
    await page.mouse.move(size.x, size.y);  // 将鼠标移动到滑块上方
    await page.mouse.down();
    await page.mouse.move(size.x + 10, size.y, {steps: Math.random(1, 9)*100});
    await sleep(Math.random()*1000);
    await page.mouse.move(size.x + 150, size.y, {steps: Math.random(1, 9)*100, delay: 1000});
    await sleep(Math.random()*1000);
    await page.mouse.move(size.x + 160, size.y, {steps: Math.random(1, 9)*100, delay: 100});
    await sleep(Math.random()*1000);
    await page.mouse.move(size.x + 500, size.y, {steps: Math.random(1, 9)*100, delay: 500})
    await sleep(Math.random()*800);
    await page.mouse.up();
    await sleep(randomNum(1, 3) * 1000);

    return;
}

export async function testMainOption(_this, event, type) {                  // 测试操作
    let error = "";
    let cookies = "";
    let browser;
    let page;
    browser = await createBrowser();
    page = (await browser.pages())[0];
    await page.goto("https://www.etax-gd.gov.cn/xxmh/html/index.html", {
        waitUntil: "networkidle2",
    });

    try {               // 关闭信息提示
        await page.click(".layui-layer-btn>a");
        await sleep(randomNum(1, 3) * 1000);
    } catch (err) {
        console.log("****** 未能获取到版本提示弹框");
    }
    await page.$(".loginico");
    await page.click(".loginico");
    await sleep(1000);
               
    await preparePageForModify(page);       // 修改JS检测参数



    try {               // 关闭版本提示检验弹框
        await page.click(".layui-layer-btn>a:nth-of-type(2)");
        await sleep(randomNum(1, 3) * 1000);
    } catch (err) {

    }

    error = await dragSlider2Verify(page);                  // 拖动滑块验证
    if (error.length != 0) {
        await closeBrowser(browser);
        return error;
    }

    return;
}